package org.dtrd.modules.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.system.util.JwtUtil;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.PeriodUnit;
import org.dtrd.modules.content.tags.entity.bean.TagsListInfo;
import org.dtrd.modules.content.tags.service.IDtrdExtEmsYwTagsService;
import org.dtrd.modules.service.entity.bean.PatientServiceDetail;
import org.dtrd.modules.service.entity.bean.PatientServiceItemKey;
import org.dtrd.modules.service.entity.bean.ServiceDetailItem;
import org.dtrd.modules.service.entity.po.DtrdRlPackagePatient;
import org.dtrd.modules.service.entity.po.DtrdRlPatientServiceDetail;
import org.dtrd.modules.service.entity.request.PatientServiceRequest;
import org.dtrd.modules.service.mapper.DtrdRlPatientServiceDetailMapper;
import org.dtrd.modules.service.service.IDtrdEntRdServiceService;
import org.dtrd.modules.service.service.IDtrdRlPackagePatientService;
import org.dtrd.modules.service.service.IDtrdRlPatientServiceDetailService;
import org.dtrd.modules.system.service.ISysUserService;
import org.dtrd.modules.util.NumberUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author QR
 * @since 2022-01-06
 */
@DS("multi-datasource1")
@Service
@Slf4j
public class DtrdRlPatientServiceDetailServiceImpl extends ServiceImpl<DtrdRlPatientServiceDetailMapper, DtrdRlPatientServiceDetail> implements IDtrdRlPatientServiceDetailService {

    @Autowired
    private IDtrdEntRdServiceService serviceService;
    @Autowired
    private IDtrdRlPackagePatientService packagePatientRlService;
    @Autowired
    private IDtrdExtEmsYwTagsService tagsService;
    @Autowired
    private ISysUserService sysUserService;

    @Override
    public boolean saveOrUpdatePatientServiceDetail(PatientServiceRequest dto, String username) {
        DtrdRlPatientServiceDetail dtrdRlPatientServiceDetail = new DtrdRlPatientServiceDetail();
        if (dto.getDataId() == null) {
            dtrdRlPatientServiceDetail = dtrdRlPatientServiceDetail.init();
        }
        dtrdRlPatientServiceDetail.parseFromDto(dto);
        if (dtrdRlPatientServiceDetail.getStatus() == 1) {
            dtrdRlPatientServiceDetail.setFinishedTime(new Date());
        }
        dtrdRlPatientServiceDetail.setExecutor(username);
        return saveOrUpdate(dtrdRlPatientServiceDetail);
    }

    @Override
    public void removePatientServiceDetailRelation(Integer patientId, Integer packageId) {
        LambdaQueryWrapper<DtrdRlPatientServiceDetail> wrapper = Wrappers.lambdaQuery(DtrdRlPatientServiceDetail.class)
                .eq(DtrdRlPatientServiceDetail::getPatientId, patientId)
                .eq(DtrdRlPatientServiceDetail::getPatientId, patientId);
        remove(wrapper);
    }

    @Override
    public boolean removePatientServiceDetail(Integer dataId) {
        return removeById(dataId);
    }

    @Override
    public boolean checkIdentity(Integer serviceDetailId, String post) {
        List<String> posts = Arrays.stream(post.split(",")).collect(Collectors.toList());
        log.info("----------当前登陆人职位：{}", post);
        // 获取服务执行人ids
        String executorIds = serviceService.getServiceExecutorsByServiceDetailId(serviceDetailId);
        String[] executorType = executorIds.split(",");
        // 有一个职位服务就返回 true
        for (String type : executorType) {
            Constant.Executor executor = Constant.Executor.valueOf(Integer.parseInt(type));
            if (posts.contains(executor.getCode())) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean hasPackageRelateToPatient(Integer packageId) {
        // 患者 & 服务包 表
        DtrdRlPackagePatient relation1 = packagePatientRlService.getOne(Wrappers.lambdaQuery(DtrdRlPackagePatient.class)
                .eq(DtrdRlPackagePatient::getPatientId, packageId)
                .last("limit 1"));
        // 患者 & 服务项目 表
        DtrdRlPatientServiceDetail relation2 = getOne(Wrappers.lambdaQuery(DtrdRlPatientServiceDetail.class)
                .eq(DtrdRlPatientServiceDetail::getPackageId, packageId)
                .last("limit 1"));
        return relation1 != null || relation2 != null;
    }

    @Override
    public boolean hasServiceRelateToPatient(Integer serviceId) {
        // 患者 & 服务项目 表
        DtrdRlPatientServiceDetail relation = getOne(Wrappers.lambdaQuery(DtrdRlPatientServiceDetail.class)
                .eq(DtrdRlPatientServiceDetail::getServiceId, serviceId)
                .last("limit 1"));
        if (relation != null) {
            int packageId = relation.getPackageId();
            List<DtrdRlPackagePatient> packagePatient = packagePatientRlService.list(Wrappers.lambdaQuery(DtrdRlPackagePatient.class)
                    .eq(DtrdRlPackagePatient::getPackageId, packageId));
            if (CollectionUtil.isNotEmpty(packagePatient)) {
                for (DtrdRlPackagePatient dtrdRlPackagePatient : packagePatient) {
                    if (dtrdRlPackagePatient.getStatus() == Constant.PackageServiceStatus.SERVICING.getType()) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    @Override
    public boolean checkServiceItemType(Integer type) {
        List<Integer> statusList = Arrays.stream(Constant.ServiceItemStatus.values())
                .map(Constant.ServiceItemStatus::getType).collect(Collectors.toList());
        return statusList.contains(type);
    }

    @Override
    public Map<PatientServiceItemKey, List<ServiceDetailItem>> getPatientServiceDetail(Integer patientId, Integer relationId) {
        LambdaQueryWrapper<DtrdRlPatientServiceDetail> wrapper = baseQueryWrapper()
                .eq(DtrdRlPatientServiceDetail::getPatientId, patientId)
                .eq(DtrdRlPatientServiceDetail::getRelationId, relationId)
                .orderByDesc(DtrdRlPatientServiceDetail::getCreateTime)
                .orderByAsc(DtrdRlPatientServiceDetail::getDataId);
        List<DtrdRlPatientServiceDetail> poList = list(wrapper);
        if (CollectionUtil.isEmpty(poList)) {
            return Collections.EMPTY_MAP;
        }
        Map<Integer, String> tagId2Name = new HashMap<>(10);
        List<TagsListInfo> infoList = tagsService.listTagsByTagType(43, null);
        for (TagsListInfo info : infoList) {
            tagId2Name.put(info.getTagId(), info.getTagName());
        }
        List<ServiceDetailItem> dtoList = poList.stream().map(po -> {
            ServiceDetailItem serviceDetailItem = new ServiceDetailItem().parseFromPO(po);
            // 服务标签
            String tagIds = po.getPatientEvaluationTagIds();
            Optional.ofNullable(tagIds).ifPresent(t -> {
                String[] tagIdStrs = t.split(",");
                List<String> tagName = Arrays.stream(tagIdStrs).map(str -> {
                    int id = Integer.parseInt(str);
                    return tagId2Name.get(id);
                }).collect(Collectors.toList());
                serviceDetailItem.setTagName(tagName);
            });
            String executor = po.getExecutor();
            if (StrUtil.isNotBlank(executor)) {
                serviceDetailItem.setExecutor(sysUserService.getRealNameByUserName(executor));
            }
            return serviceDetailItem;
        }).collect(Collectors.toList());
        // 列表按照周期正序排序
        CollectionUtil.sort(dtoList, Comparator.comparing(ServiceDetailItem::getPeriod));
        LinkedHashMap<PatientServiceItemKey, List<ServiceDetailItem>> resultMap = new LinkedHashMap<>();
        dtoList.forEach(dto -> {
            Integer period = dto.getPeriod();
            PatientServiceItemKey key = new PatientServiceItemKey();
            key.setPeriod(getPeriodName(period, dto.getPeriodUnit()));
            key.setPeriodNum(period);
            key.setUnit(dto.getPeriodUnit());
            List<ServiceDetailItem> serviceDetailItems = resultMap.get(key);
            if (CollectionUtil.isEmpty(serviceDetailItems)) {
                ArrayList<ServiceDetailItem> list = new ArrayList<>();
                list.add(dto);
                resultMap.put(key, list);
            } else {
                serviceDetailItems.add(dto);
            }
        });
        // 设置是否完成的标记
        DtrdRlPackagePatient one = packagePatientRlService.getById(relationId);
        DateTime serviceStartDate = new DateTime(one.getStartTime());
        Date today = DateUtils.getDateYMD();
        LinkedHashMap<PatientServiceItemKey, List<ServiceDetailItem>> realResultMap = new LinkedHashMap<>();
        Set<PatientServiceItemKey> keySet = resultMap.keySet();
        for (PatientServiceItemKey key : keySet) {
            List<ServiceDetailItem> serviceDetailItems = resultMap.get(key);
            // (标记只需要设置服务中状态的包)
            if (one.getStatus().equals(Constant.PackageServiceStatus.SERVICING.getType())) {
                Integer periodNum = key.getPeriodNum();
                if (compareDate(serviceStartDate, today, periodNum == 0)) {
                    int finishedCount = 0;
                    for (ServiceDetailItem serviceDetailItem : serviceDetailItems) {
                        if (serviceDetailItem.getStatus() == Constant.FINISHED) {
                            finishedCount++;
                        }
                    }
                    // 对比 finish 状态的服务项和该周期内的服务项个数
                    if (finishedCount != serviceDetailItems.size()) {
                        key.setNotFinished(true);
                    }
                }
                if (periodNum >= 1) {
                    serviceStartDate = DateUtil.offset(serviceStartDate, DateField.MONTH, 1);
                }
                today = DateUtil.beginOfMonth(today);
            }
            realResultMap.put(key, serviceDetailItems);
        }
        return realResultMap;
    }

    private boolean compareDate(Date serviceDate, Date today, boolean isFirstDay) {
        if (isFirstDay) {
            return DateUtil.compare(serviceDate, today) < 0;
        } else {
            DateTime beginOfMonth = DateUtil.beginOfMonth(today);
            return DateUtil.compare(serviceDate, beginOfMonth) < 0;
        }
    }

    @Override
    public String getPatientPackageSchedule(Integer patientId, Integer packageId) {
        LambdaQueryWrapper<DtrdRlPackagePatient> queryWrapper = Wrappers.lambdaQuery(DtrdRlPackagePatient.class)
                .eq(DtrdRlPackagePatient::getPackageId, packageId)
                .eq(DtrdRlPackagePatient::getPatientId, patientId);
        DtrdRlPackagePatient one = packagePatientRlService.getOne(queryWrapper);
        if (one == null || one.getStartTime() == null) {
            return "加入当天";
        }
        // 获取当前日期与服务日期相差的月份
        Date startTime = one.getStartTime();
        DateTime now = new DateTime();
        Date endTime = one.getEndTime();
        long betweenStartAndEnd = DateUtil.between(startTime, endTime, DateUnit.DAY);
        long betweenStartAndNow = DateUtil.between(now, startTime, DateUnit.DAY);
        if (betweenStartAndNow <= 1) {
            return "加入当天";
        }
        if (betweenStartAndNow >= betweenStartAndEnd) {
            return getPeriodName(getPeriodByDays(betweenStartAndEnd) - 1, one.getPeriodUnit());
        }
        return getPeriodName(getPeriodByDays(betweenStartAndNow), one.getPeriodUnit());
    }

    @Override
    public boolean savePatientEvaluation(Integer itemId, Integer evaluation, List<Integer> tagIds) {
        DtrdRlPatientServiceDetail serviceDetail = getById(itemId);
        if (serviceDetail == null || serviceDetail.getStatus().equals(Constant.ServiceItemStatus.NOT_DONE.getType())) {
            return false;
        }
        if (CollectionUtil.isNotEmpty(tagIds)) {
            StringJoiner joiner = new StringJoiner(",");
            for (Integer tagId : tagIds) {
                joiner.add(tagId.toString());
            }
            serviceDetail.setPatientEvaluationTagIds(joiner.toString());
        }
        serviceDetail.setPatientEvaluation(evaluation);
        return updateById(serviceDetail);
    }

    private LambdaQueryWrapper<DtrdRlPatientServiceDetail> baseQueryWrapper() {
        return Wrappers.lambdaQuery(DtrdRlPatientServiceDetail.class)
                .eq(DtrdRlPatientServiceDetail::getIsDel, 0);
    }

    private LambdaUpdateWrapper<DtrdRlPatientServiceDetail> baseUpdateWrapper() {
        return Wrappers.lambdaUpdate(DtrdRlPatientServiceDetail.class)
                .eq(DtrdRlPatientServiceDetail::getIsDel, 0);
    }

    private static String getPeriodName(int num, Integer periodUnit) {
        if (num == 0) {
            return "加入当天";
        }
        if (num >= 10 && num < 20) {
            return "第" + NumberUtil.int2chineseNum(num).substring(1);
        }
        String periodName = NumberUtil.int2chineseNum(num);
        PeriodUnit unit = Optional.ofNullable(PeriodUnit.valueOf(periodUnit)).orElse(PeriodUnit.MONTH);
        if (unit == PeriodUnit.MONTH) {
            return "第" + periodName + "个月";
        } else {
            return "第" + periodName + unit.getName();
        }
    }

    private static int getPeriodByDays(long betweenDays) {
        return (int) (betweenDays - betweenDays % 30) / 30 + 1;
    }
}
